//
//  NSDecimalNumber+MZBase.m
//  MZBaseDemo
//
//  Created by Chris Yang on 2016/12/5.
//  Copyright © 2016年 Chris Yang. All rights reserved.
//

#import "NSDecimalNumber+MZBase.h"

@implementation NSDecimalNumber(MZBase)

#pragma mark - Base Operation

#pragma mark Decimal op Decimal

- (NSDecimalNumber *)mzAdd:(NSDecimalNumber *)inputNum {
    
    if (NO == mzDecimalIsValid(self)) {
        return mzDecimalInitVal;
    }
    
    if (NO == mzDecimalIsValid(inputNum)) {
        return self;
    }

    return [self decimalNumberByAdding:inputNum];
}

- (NSDecimalNumber *)mzSub:(NSDecimalNumber *)inputNum {
    
    if (NO == mzDecimalIsValid(self)) {
        return mzDecimalInitVal;
    }
    
    if (NO == mzDecimalIsValid(inputNum)) {
        return self;
    }
    
    return [self decimalNumberBySubtracting:inputNum];
}

- (NSDecimalNumber *)mzMul:(NSDecimalNumber *)inputNum {
    
    if (NO == mzDecimalIsValid(self)) {
        return mzDecimalInitVal;
    }
    
    if (NO == mzDecimalIsValid(inputNum)) {
        return self;
    }
    
    return [self decimalNumberByMultiplyingBy:inputNum];
}

- (NSDecimalNumber *)mzDiv:(NSDecimalNumber *)inputNum {
    
    if (NO == mzDecimalIsValid(self)) {
        return mzDecimalInitVal;
    }
    
    if (NO == mzDecimalIsValid(inputNum)
        || 0 == inputNum.doubleValue) {
        return self;
    }

    return [self decimalNumberByDividingBy:inputNum];
}

#pragma mark Decimal op NSString

- (NSDecimalNumber *)mzAddStr:(NSString *)inputStr {
    return [self mzAdd:[NSDecimalNumber mzDecimalNumberFromNSString:inputStr]];
}

- (NSDecimalNumber *)mzSubStr:(NSString *)inputStr {
    return [self mzSub:[NSDecimalNumber mzDecimalNumberFromNSString:inputStr]];
}

- (NSDecimalNumber *)mzMulStr:(NSString *)inputStr {
    return [self mzMul:[NSDecimalNumber mzDecimalNumberFromNSString:inputStr]];
}

- (NSDecimalNumber *)mzDivStr:(NSString *)inputStr {
    return [self mzDiv:[NSDecimalNumber mzDecimalNumberFromNSString:inputStr]];
}

#pragma mark Decimal op NSNumber

- (NSDecimalNumber *)mzAddNum:(NSNumber *)inputNum {
    return [self mzAdd:[NSDecimalNumber mzDecimalNumberFromNumber:inputNum]];
}

- (NSDecimalNumber *)mzSubNum:(NSNumber *)inputNum {
    return [self mzSub:[NSDecimalNumber mzDecimalNumberFromNumber:inputNum]];
}

- (NSDecimalNumber *)mzMulNum:(NSNumber *)inputNum {
    return [self mzMul:[NSDecimalNumber mzDecimalNumberFromNumber:inputNum]];
}

- (NSDecimalNumber *)mzDivNum:(NSNumber *)inputNum {
    return [self mzDiv:[NSDecimalNumber mzDecimalNumberFromNumber:inputNum]];
}

#pragma mark - Base Formatter */

- (NSDecimalNumber *)mzRoundingValWithScale:(NSInteger)scale {
    
    NSDecimalNumber *tmpNum = mzDecimalValidVal(self);
    NSDecimalNumberHandler *numberHandler =
    [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain
                                                           scale:scale
                                                raiseOnExactness:NO
                                                 raiseOnOverflow:NO
                                                raiseOnUnderflow:NO
                                             raiseOnDivideByZero:YES];
    
    tmpNum = [tmpNum decimalNumberByRoundingAccordingToBehavior:numberHandler];
    return tmpNum;
}

#pragma mark - Safe Decimal Construction

+ (NSDecimalNumber *)mzDecimalNumberFromNSString:(NSString *)str {
    
    NSDecimalNumber *tmpNum = [NSDecimalNumber decimalNumberWithString:str];
    
    return mzDecimalValidVal(tmpNum);
}

+ (NSDecimalNumber *)mzDecimalNumberFromNumber:(NSNumber *)num {
    
    NSDecimal tmpDecimal = [num decimalValue];
    NSDecimalNumber *tmpNum = [NSDecimalNumber decimalNumberWithDecimal:tmpDecimal];
    
    return mzDecimalValidVal(tmpNum);
}

@end
